/**
 * Copyright (c) 2014, 2016 itemis AG (http://www.itemis.eu) and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.xtend.core.tests.compiler;

import org.eclipse.xtend2.lib.StringConcatenation;
import org.junit.Test;

/**
 * @author Sebastian Zarnekow - Initial contribution and API
 */
@SuppressWarnings("all")
public class CompilerBug383534Test extends AbstractXtendCompilerTest {
  @Test
  public void test_01() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("class C {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("def void m() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val (String,String)=>String strAdd = [s1,s2 | s1+s2]");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val /*(String)=>String*/ curriedStrAdd = strAdd.curry(\'x\') // ok");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(strAdd.apply(\'x\', \'y\')) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(curriedStrAdd.apply(\'y\')) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val (String,String[])=>String strAdd2 = [s1,s2 | s1 + s2.reduce[x1,x2 | x1+x2]]");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val /*(String)=>String*/ curriedStrAdd2 = strAdd2.curry(\'x\') // fail");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(strAdd2.apply(\'x\', newArrayList(\'y\', \'z\'))) // result: \'xyz\'");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(curriedStrAdd2.apply(newArrayList(\'y\', \'z\'))) // should result in \'xyz\'");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    StringConcatenation _builder_1 = new StringConcatenation();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.CollectionLiterals;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Conversions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.FunctionExtensions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function1;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function2;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.InputOutput;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.IterableExtensions;");
    _builder_1.newLine();
    _builder_1.newLine();
    _builder_1.append("@SuppressWarnings(\"all\")");
    _builder_1.newLine();
    _builder_1.append("public class C {");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("public void m() {");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<String, String, String> _function = (String s1, String s2) -> {");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("return (s1 + s2);");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<? super String, ? super String, ? extends String> strAdd = _function;");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function1<String, String> curriedStrAdd = FunctionExtensions.<String, String, String>curry(strAdd, \"x\");");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(strAdd.apply(\"x\", \"y\"));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(curriedStrAdd.apply(\"y\"));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<String, String[], String> _function_1 = (String s1, String[] s2) -> {");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("final Function2<String, String, String> _function_2 = (String x1, String x2) -> {");
    _builder_1.newLine();
    _builder_1.append("        ");
    _builder_1.append("return (x1 + x2);");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("String _reduce = IterableExtensions.<String>reduce(((Iterable<? extends String>)Conversions.doWrapArray(s2)), _function_2);");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("return (s1 + _reduce);");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<? super String, ? super String[], ? extends String> strAdd2 = _function_1;");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function1<String[], String> curriedStrAdd2 = FunctionExtensions.<String, String[], String>curry(strAdd2, \"x\");");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(strAdd2.apply(\"x\", ((String[])Conversions.unwrapArray(CollectionLiterals.<String>newArrayList(\"y\", \"z\"), String.class))));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(curriedStrAdd2.apply(((String[])Conversions.unwrapArray(CollectionLiterals.<String>newArrayList(\"y\", \"z\"), String.class))));");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("}");
    _builder_1.newLine();
    _builder_1.append("}");
    _builder_1.newLine();
    this.assertCompilesTo(_builder, _builder_1);
  }

  @Test
  public void test_02() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("class C {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("def void m() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val (String,String)=>String strAdd = [s1,s2 | s1+s2]");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val curriedStrAdd = strAdd.curry(\'x\')");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(strAdd.apply(\'x\', \'y\')) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(curriedStrAdd.apply(\'y\')) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    StringConcatenation _builder_1 = new StringConcatenation();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.FunctionExtensions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function1;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function2;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.InputOutput;");
    _builder_1.newLine();
    _builder_1.newLine();
    _builder_1.append("@SuppressWarnings(\"all\")");
    _builder_1.newLine();
    _builder_1.append("public class C {");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("public void m() {");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<String, String, String> _function = (String s1, String s2) -> {");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("return (s1 + s2);");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<? super String, ? super String, ? extends String> strAdd = _function;");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function1<String, String> curriedStrAdd = FunctionExtensions.<String, String, String>curry(strAdd, \"x\");");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(strAdd.apply(\"x\", \"y\"));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(curriedStrAdd.apply(\"y\"));");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("}");
    _builder_1.newLine();
    _builder_1.append("}");
    _builder_1.newLine();
    this.assertCompilesTo(_builder, _builder_1);
  }

  @Test
  public void test_03() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("class C {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("def void m() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val (String,String[])=>String strAdd = [s1,s2 | s1+s2.head]");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val curriedStrAdd = strAdd.curry(\'x\')");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(strAdd.apply(\'x\', newArrayList(\'y\', \'z\')))");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(curriedStrAdd.apply(newArrayList(\'y\', \'z\')))");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    StringConcatenation _builder_1 = new StringConcatenation();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.CollectionLiterals;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Conversions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.FunctionExtensions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function1;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function2;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.InputOutput;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.IterableExtensions;");
    _builder_1.newLine();
    _builder_1.newLine();
    _builder_1.append("@SuppressWarnings(\"all\")");
    _builder_1.newLine();
    _builder_1.append("public class C {");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("public void m() {");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<String, String[], String> _function = (String s1, String[] s2) -> {");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("String _head = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(s2)));");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("return (s1 + _head);");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<? super String, ? super String[], ? extends String> strAdd = _function;");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function1<String[], String> curriedStrAdd = FunctionExtensions.<String, String[], String>curry(strAdd, \"x\");");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(strAdd.apply(\"x\", ((String[])Conversions.unwrapArray(CollectionLiterals.<String>newArrayList(\"y\", \"z\"), String.class))));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(curriedStrAdd.apply(((String[])Conversions.unwrapArray(CollectionLiterals.<String>newArrayList(\"y\", \"z\"), String.class))));");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("}");
    _builder_1.newLine();
    _builder_1.append("}");
    _builder_1.newLine();
    this.assertCompilesTo(_builder, _builder_1);
  }

  @Test
  public void test_04() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("class C {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("def void m() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val (String,String[])=>String strAdd = [s1,s2 | s1+s2.reduce[x1,x2 | x1+x2]]");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("val curriedStrAdd = strAdd.curry(\'x\')");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(strAdd.apply(\'x\', #[\'y\'])) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("println(curriedStrAdd.apply(#[\'y\'])) // result: \'xy\'");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    StringConcatenation _builder_1 = new StringConcatenation();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Conversions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.FunctionExtensions;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function1;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.Functions.Function2;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.InputOutput;");
    _builder_1.newLine();
    _builder_1.append("import org.eclipse.xtext.xbase.lib.IterableExtensions;");
    _builder_1.newLine();
    _builder_1.newLine();
    _builder_1.append("@SuppressWarnings(\"all\")");
    _builder_1.newLine();
    _builder_1.append("public class C {");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("public void m() {");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<String, String[], String> _function = (String s1, String[] s2) -> {");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("final Function2<String, String, String> _function_1 = (String x1, String x2) -> {");
    _builder_1.newLine();
    _builder_1.append("        ");
    _builder_1.append("return (x1 + x2);");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("String _reduce = IterableExtensions.<String>reduce(((Iterable<? extends String>)Conversions.doWrapArray(s2)), _function_1);");
    _builder_1.newLine();
    _builder_1.append("      ");
    _builder_1.append("return (s1 + _reduce);");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("};");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function2<? super String, ? super String[], ? extends String> strAdd = _function;");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("final Function1<String[], String> curriedStrAdd = FunctionExtensions.<String, String[], String>curry(strAdd, \"x\");");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(strAdd.apply(\"x\", new String[] { \"y\" }));");
    _builder_1.newLine();
    _builder_1.append("    ");
    _builder_1.append("InputOutput.<String>println(curriedStrAdd.apply(new String[] { \"y\" }));");
    _builder_1.newLine();
    _builder_1.append("  ");
    _builder_1.append("}");
    _builder_1.newLine();
    _builder_1.append("}");
    _builder_1.newLine();
    this.assertCompilesTo(_builder, _builder_1);
  }
}
